/*
  +----------------------------------------------------------------------+
  | PHP Version 7                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2016 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_sign.h"

/* If you declare any globals in php_sign.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(sign)
*/

/* True global resources - no need for thread safety here */
static int le_sign;

/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("sign.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_sign_globals, sign_globals)
    STD_PHP_INI_ENTRY("sign.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_sign_globals, sign_globals)
PHP_INI_END()
*/
/* }}} */

/* Remove the following function when you have successfully modified config.m4
   so that your module can be compiled into PHP, it exists only for testing
   purposes. */

/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_sign_compiled(string arg)
   Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_sign_compiled)
{
	char *arg = NULL;
	size_t arg_len, len;
	zend_string *strg;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
		return;
	}

	strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "sign", arg);

	RETURN_STR(strg);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and
   unfold functions in source code. See the corresponding marks just before
   function definition, where the functions purpose is also documented. Please
   follow this convention for the convenience of others editing your code.
*/


/* {{{ php_sign_init_globals
 */
/* Uncomment this function if you have INI entries
static void php_sign_init_globals(zend_sign_globals *sign_globals)
{
	sign_globals->global_value = 0;
	sign_globals->global_string = NULL;
}
*/
/* }}} */

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(sign)
{
	/* If you have INI entries, uncomment these lines
	REGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(sign)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(sign)
{
#if defined(COMPILE_DL_SIGN) && defined(ZTS)
	ZEND_TSRMLS_CACHE_UPDATE();
#endif
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(sign)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(sign)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "sign support", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
}
/* }}} */

/* {{{ sign_functions[]
 *
 * Every user visible function must have an entry in sign_functions[].
 */
const zend_function_entry sign_functions[] = {
	PHP_FE(confirm_sign_compiled,	NULL)		/* For testing, remove later. */
        /* 函数注册列表 */
        PHP_FE(sign_make,	NULL)       /* 注册sign_make函数 */
        PHP_FE(sign_verify,	NULL)       /* 注册sign_verify函数 */
	PHP_FE_END	/* Must be the last line in sign_functions[] */
};
/* }}} */

/* {{{ sign_module_entry
 */
zend_module_entry sign_module_entry = {
	STANDARD_MODULE_HEADER,
	"sign",
	sign_functions,
	PHP_MINIT(sign),
	PHP_MSHUTDOWN(sign),
	PHP_RINIT(sign),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(sign),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(sign),
	PHP_SIGN_VERSION,
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_SIGN
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(sign)
#endif

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */

/*
 * 函数定义实现列表
 */
int php_sample_print_zval(zval *ele TSRMLS_DC, zval *sign_str)
{   
    zval temp = *ele; // 临时zval，避免convert_to_string 污染原元素
    zval_copy_ctor(&temp);  // 分配新 zval 空间并复制 ele 的值
    convert_to_string(&temp); // 字符串类型转换

    //简单的打印
//    PHPWRITE(Z_STRVAL(temp), Z_STRLEN(temp));
//    php_printf("\n");
    zval_dtor(&temp); //释放临时的 temp
    return ZEND_HASH_APPLY_KEEP;
}

/*
 * 数据签名
 * @param array data       签名数据
 * @param string token     签名秘钥
 * @return string
 * */
PHP_FUNCTION(sign_make)
{
    
    ulong num_key;
    zend_string *key, *sign;
    zval *arr, *val;
    HashTable *arr_hash;
    int array_count;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
        RETURN_NULL();
    }

    arr_hash = Z_ARRVAL_P(arr);
    array_count = zend_hash_num_elements(arr_hash);
    php_printf("数组元素(个)： %d \n", array_count);
    
    ZEND_HASH_FOREACH_KEY_VAL(arr_hash, num_key, key, val) {
        
        // 转字符串
        convert_to_string(val);
        
        php_printf("<br/>");
        php_printf(Z_STRVAL_P(val));
        
//        switch(Z_TYPE_P(val)){
//            case IS_NULL:
//                php_printf("null");
//                break;
//            case IS_TRUE:
//                php_printf("true");
//                break;
//            case IS_FALSE:
//                php_printf("false");
//                break;
//            case IS_LONG:
//                php_printf("long");
//                break;
//            case IS_DOUBLE:
//                php_printf("double");
//                break;
//            case IS_STRING:
//                php_printf("string\n");
//                
//                break;
//        }
        
    }ZEND_HASH_FOREACH_END();
    
    
    // 定义函数参数
//    zval *data;              // 签名数组数据          
//    zend_string *token;      // 签名秘钥
//    size_t token_len;        // 秘钥长度
//    HashTable *arr_hash;     // 数组Hash类型
//    
//    // 获取脚本参数
//    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "as", &data, &token, &token_len)){
//        return ;
//    }
//    
//    // 数组按字母顺序排序
//    // 创建数组HashTable
//    arr_hash = Z_ARRVAL_P(data);
//    
//    // 遍历Hash表
//    //生成一个名为arrht、元素为zval*类型的HashTable
//    zend_hash_apply(arr_hash, (apply_func_t)callback TSRMLS_CC);
//    
//    php_printf(array_val_str);

    
    // 返回数组
    //RETURN_ZVAL(data, 1, 1);
    //RETURN_STR(token);
}

/* 验签 */
PHP_FUNCTION(sign_verify)
{
    php_printf("Sign Verify Success!");
    RETURN_TRUE;
}
